package shared.runtime

import org.jgroups._

import java.io._
import shared.file._
import shared.message.chat._
import shared.message._
import scala.xml.XML
import shared.file.FileTransferCollection

trait Runtime {

  def username: String
  
  def host: String
  
  def filesystem: Filesystem
  
  val channelName: String
  
  @volatile var nodes: List[AddressInformation] = Nil
  
  @volatile var chatListeners: List[ChatMessageListener] = Nil
  
  def addNode(info: AddressInformation) =  this.synchronized{  if(!nodes.contains(info)) nodes = info :: nodes }
  
  def addChatListener(l: ChatMessageListener) = this.synchronized{ chatListeners = l :: chatListeners}
  
  def channel: ChannelAdaptor
  
  def localAddress = channel.localAddress
  
  def responseHandler: ResponseHandler 

  def timeout = 10000L
  
  def saveConfig = XML.save(RuntimeFactory.configFile.getAbsolutePath, toXML, "UTF-8")

  lazy val server = new shared.server.FileServer(filesystem, this.uploading)
  
  @volatile 
  var dropDirectory: Option[SharedFolder] = None
  
  def close = {
    channel.close
    saveConfig
    server.stop
  }
  
  def toXML = <lan> {filesystem.toXML} <channel>{channelName}</channel></lan>
  
  val downloading = new FileTransferCollection("Downloading")
  
  val uploading = new FileTransferCollection("Uploading")
    
}

object RuntimeFactory {
  val configFolder = new File(System.getProperty("user.home")+"/lan")
  if(!configFolder.exists) {
    if(!configFolder.mkdirs) {
      error("cannot create config folder on: " + configFolder.getAbsolutePath)
    }
  }
  
  val configFile = new File(configFolder, "lan.xml")
  if(configFile.exists) {
    println("loading configuration from: " + configFile.getAbsolutePath)
  } else {
    println("no config file found")
  }
  
  val rootElement = XML.loadFile(configFile)
  
  def apply() = {
    val fsEls = rootElement \ "fs"
    
    val chan = (rootElement \ "channel").text
    
    val fs = if(fsEls.isEmpty) { new Filesystem() } else {Filesystem.fromXML(fsEls(0))}
    val jc = createJChannel
    val adaptor = new JChannelChannel(createJChannel)
    val r = new RuntimeImpl(fs, adaptor, adaptor, jc, chan)
    r.server.start
    r
  }
  
  def createJChannel = new org.jgroups.JChannel
  
  
}